#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct s_files {
  const char *name;
  long addr;
  long size;
};

static long g_addr = 0;

long addr_str_bin(const char *addr) {
  char *ptr;
  return strtol(addr, &ptr, 16);
}
long file_size(const char *file) {
  FILE *fp = fopen(file, "r");
  fseek(fp, 0, SEEK_SET);
  long lb = ftell(fp);
  fseek(fp, 0, SEEK_END);
  long le = ftell(fp);
  fclose(fp);
  return le - lb;
}
void write_zero(FILE *f, long size) {
  if (size <= 0) return; 
  void *buff = malloc(size);
  bzero(buff, size);
  fwrite(buff, sizeof(char), size, f);
  free(buff);
}
bool write_file(FILE *f, s_files &sf) {
  FILE *fp = fopen(sf.name, "rb");
  if (!fp) return false;

  char buff[1024] = { 0 };
  int count, errno=0;

  if (g_addr < sf.addr) {
    write_zero(f, sf.addr - g_addr);
    g_addr += sf.addr - g_addr;
  }

  if (g_addr != sf.addr)
    return false;

  while (!feof (fp)){
    count = fread(buff, sizeof(char), 1024, fp);
    fwrite(buff, sizeof(char), count, f);
    g_addr += count;
  }

  fclose(fp);

  return true;
}

void work(const char *out, std::vector<s_files>&files) {
  g_addr = 0;
  FILE *fp = fopen(out, "wb");
  for (auto &sf : files) {
    printf("%s,%ld,%ld\n", sf.name, sf.addr, sf.size);
    if (!write_file(fp, sf)) {
      printf("error.\n");
      break;
    }
  }
  fclose(fp);
}

int main(int argc, char **argv) {
  if (argc < 4)
    return -1;

  std::vector<s_files> files;
  for (int i = 2; i < argc; i += 2) {
    s_files sf = { 0 };
    sf.name = argv[i];
    sf.addr = addr_str_bin(argv[i+1]);
    sf.size = file_size(sf.name);
    files.push_back(sf);
  }
  work(argv[1], files);
  return 0;
}